package com.lightsh.sms;

import java.util.List;
import com.lightsh.sms.SmsConstants.SMS;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

public abstract class SmsMonitor {
	
	public static final String TAG = "SmsMonitor";
	private Context mContext;
	private ContentObserver mObserver;
	private Handler mHandler;
	
	private boolean mbMonitorReceiveOnly = false;
	
	/**
	 *  处理收到的目标sms消息。注意该方法运行在子线程，不要做UI操作
	 *  @return 返回true则会删除该消息,否则不删除
	 */
	public abstract boolean handleTargetSms(SmsInfo sms);
	
	/**
	 * 返回该新收到的短信是否需要监听的消息。注意该方法运行在子线程，不要做UI操作
	 */
	public abstract boolean isTargetSms(SmsInfo info);
	
	
	private class MyHandler extends Handler{
		public MyHandler(Looper looper){
			super(looper);
		}
		@Override
		public void handleMessage(Message msg) {
			switch(msg.what){
				// not used
			}
			super.handleMessage(msg);
		}
	}
	
	/**
	 * 
	 * @param context
	 * @param monitorReceiveOnly	是否只监听收到的短信
	 */
	public SmsMonitor(Context context, boolean monitorReceiveOnly){
		mContext = context;
		mbMonitorReceiveOnly = monitorReceiveOnly;
		
		HandlerThread handlerThread = new HandlerThread("background_thread");
		handlerThread.start();
		mHandler = new MyHandler(handlerThread.getLooper());
		mObserver = new SmsObserver(mHandler);
	}
	
	/**
	 * 必须调用该方法以开始监听,使用完毕需要调用{@link #endMonitor()}来结束监听
	 */
	public void startMonitor(){
		mContext.getContentResolver().registerContentObserver(Uri.parse(SmsConstants.SMS_URI_ALL), true, mObserver);
	}
	/**
	 * 调用该方法来结束监听
	 */
	public void endMonitor(){
		try{
			mContext.getContentResolver().unregisterContentObserver(mObserver);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	
	private class SmsObserver extends ContentObserver{
		
		private static final String SELECTION_RECEIVE_LATEST = SMS.ID + " > %s" +
			    " and " + SMS.TYPE + " = " + SMS.SMS_TYPE_INBOX ;
		
		private static final String SELECTION_RECEIVE_SEND_LATEST =  SMS.ID + " > %s" +
//			     " and " + SMS.PROTOCOL + " = null" +
//			     " or " + SMS.PROTOCOL + " = " + SMS.PROTOCOL_SMS + ")" +
			    " and (" + SMS.TYPE + " = " + SMS.SMS_TYPE_INBOX +
			    " or " + SMS.TYPE + " = " + SMS.SMS_TYPE_SENT + ")";
		
		private long mLatestId = 0;

		public SmsObserver(Handler handler) {
			super(handler);			
			mLatestId = SmsConstants.getMaxId(mContext);
			if(SmsConstants.DEBUG){
				Log.w(TAG, "max id = " + mLatestId);
			}
		}
		
		private void onSmsDbChange(){
			String selection;
			if(mbMonitorReceiveOnly){
				selection = String.format(SELECTION_RECEIVE_LATEST, mLatestId);
			}else{
				selection = String.format(SELECTION_RECEIVE_SEND_LATEST, mLatestId);
			}			
			List<SmsInfo> list = SmsConstants.getSmsInfo(mContext, Uri.parse(SmsConstants.SMS_URI_ALL), selection);
			if(SmsConstants.DEBUG){
				if(list.size() == 0){
					Log.i(TAG, "removeTargetReceive list is empty");
				}else{
					SmsConstants.logSms(TAG + " change list item", list);
				}
			}
			for(SmsInfo info : list){
				if(info.getId() > mLatestId){
					mLatestId = info.getId();
				}
				if(isTargetSms(info)){
					if(handleTargetSms(info)){
						Log.i(TAG, "delete receive latest sms " + info.getPhoneNumber());
						SmsConstants.deleteSms(mContext, info.getId());
					}
				}else{
					if(SmsConstants.DEBUG){
						Log.d(TAG, "receive latest sms not target " + info.getPhoneNumber() + ", skip it");
					}
				}
			}
		}

		@Override
		public void onChange(boolean selfChange) {
			if(SmsConstants.DEBUG){
				Log.d(TAG, "sms db observer onChange... " + selfChange);
			}
			onSmsDbChange();
		}
    	
    }
}
